#!/usr/bin/env python

import random
import math

class dicetest(object):
    def testsel(self):
        test = input('What kind of test is this?\n'
                     + '1. Success\n'
                     + '2. Opposed\n'
                     + '3. Extended\n'
                     + '4. Quick Extended\n'
                     + 'Enter number next to test required: ')
        return int(test)

    def success(self): #Success Test
        total = int(input("Dice pool: "))
        trsh = int(input('What is the threshold? ')) #Min. hits to succeed
        if total < trsh: print("Too few dice")
        else:
            dt = dicethrow()
            throws = dt.throw(total)
            hits = dt.htest(throws)
            glit = dt.gtest(throws)
            if glit:  crit = dt.ctest(hits)
            print (throws)
            print ("Hits: " + str(hits))
            if glit:
                if crit: print ("Critical Glitch")
                else: print ("Glitch")
            if hits >= trsh+4: print("Critical Success")
            elif hits >= trsh: print("Success")
            else: print ("Failure")
        return None

    def opposed(self): #Opposed Test
        act = int(input("Acting character's dice pool: "))
        opp = int(input("Opposing character's dice pool: "))
        yn = input('Opposed by group? (Y/N) ')
        group = False
        if yn == "Y": group = True
        elif yn == "N": group = False
        if group:
            add = int(input('Additional characters in group: '))
            opp = opp + add
        dt = dicethrow()
        athrows = dt.throw(act)
        ahits = dt.htest(athrows)
        aglit = dt.gtest(athrows)
        if aglit:  acrit = dt.ctest(ahits)
        othrows = dt.throw(opp)
        ohits = dt.htest(othrows)
        oglit = dt.gtest(othrows)
        if oglit:  ocrit = dt.ctest(ohits)
        print("Acting throws: \n" + str(athrows))
        print("Acting Hits: " + str(ahits))
        if aglit:
            if acrit: print ("Acting Critical Glitch")
            else: print ("Acting Glitch")
        print ("Opposing throws: \n" + str(othrows))
        print ("Opposing Hits: " + str(ohits))
        if oglit:
            if ocrit: print ("Opposing Critical Glitch")
            else: print ("Opposing Glitch")
        if ahits > ohits+4: print ("Critical Success")
        elif ahits > ohits: print ("Success")
        else: print ("Failure")
        return None

class extended(object):
    def extendedsel(self):
        group = False
        ext = input("Single character?(Y/N) ")
        if ext == "N": group = True
        return group

    def quicktest(self):
        total = int(input("Dice pool: "))
        trsh = int(input('What is the threshold? ')) #Min. hits to succeed
        intl = int(input('What is the interval length? '))
        intt = input('What is the interval type (i.e. minutes, days, etc)? ')
        dt = dicethrow()
        throws = dt.throw(total)
        hits = dt.htest(throws)
        glit = dt.gtest(throws)
        print (throws)
        if glit:
            crit = dt.ctest(hits)
            if crit: print("Critical Glitch Test Failed")
            else:
                print ("Glitch" )
                gthrows = dt.throw(1) # Rolls 1D6
                hits = hits - gthrow[0] #Subtracts value of 1D6 throw from hits
        if hits == 0: print ("No Hits Test Failed") #No or hits after glitch
        else:
            avg = int(math.ceil(trsh/hits)) #Average number of test to
            if avg == 1: avg+= 1
            time = avg*intl #Total time required to meet threshold
            print (avg)
            print ("Test Succeds in " + str(time) + " " + intt)
        return None

    def singletest(self):
        total = int(input("Dice pool: "))
        trsh = int(input('What is the threshold? ')) #Min. hits to succeed
        intl = int(input('What is the interval length? '))
        intt = input('What is the interval type (i.e. minutes, days, etc)? ')
        group = False
        ltst = input("Time limit?(Y/N) ")
        if ltst == "Y":
            lim = int(input('What is the maximum interval length? '))
        else: lim = 1000000
        tot = 0
        tests = 0
        while total > 0:
            tests += 1
            time = tests*intl #Total time
            if time > lim:
                print ("Out of Time")
                break
            dt = dicethrow()
            throws = dt.throw(total)
            print (throws)
            hits = dt.htest(throws)
            tot = tot + hits
            glit = dt.gtest(throws)
            if glit:
                crit = dt.ctest(hits)
                if crit:
                    print ("Critical Glitch Test Failed")
                    fail = False
                    break
                else:
                    print ("Glitch")
                    gthrows = dt.throw(1) # Rolls 1D6
                    tot = tot - gthrow[0] #Subtracts value of 1D6 throw from hits
                    if tot == 0: #No or hits after glitch
                         print ("No Hits After Glitch Test Failed")
                         fail = False
                         break
            if tot >= trsh:
                print ("Test Succeds in " + int(time) + " " + intt)
                fail = False
                break
            total -= 1
            fail = True
        if fail: print ("Test Failed Threshold Not Met In Time")
        return None

    def grouptest(self):
        chartot = int(input("The number of characters: "))
        pool = []
        dice = 0
        i = 0
        print("Input character dice pools in descending order:\n")
        while i < chartot:
            dice = input("Character " + str(i+1) + " dice pool: ")
            pool.append(dice)
            i += 1
        trsh = int(input('What is the threshold? ')) #Min. hits to succeed

class dicethrow(object):
    def throw(self, num): #Generates the dice throws
        dice = []
        x = 0
        while  x < num:
            roll = random.randint(1,6)
            dice.append(roll)
            x += 1
        return dice

    def htest(self, dice): #Counts number of fives or sixes
        hits = 0
        num = len(dice)
        for throw in range(num):
        	if dice[throw] > 4: hits += 1
        return hits

    def gtest(self, dice): #Determines if glitch occurs
        glct = 0 #number of ones
        glit = False
        threh = 0 #glitch threshold
        num = len(dice)
        threh = int(math.ceil(num/2.0)) #Threshold is half total dice rounded up
        for throw in range(num):
            if dice[throw] == 1: glct += 1
        if glct > threh:
            glit = True #If number of ones greater than threshold glitch occurs
        return glit

    def ctest(self, hits): #Determines if glitch critical
        crit = False
        if hits == 0: crit = True
        return crit

dtst = dicetest()
etst = extended()

tst = dtst.testsel()
if tst == 1: dtst.success()
elif tst == 2: dtst.opposed()
elif tst == 3:
    group = etst.extendedsel()
    if group: etst.grouptest()
    else: etst.singletest()
elif tst == 4: etst.quicktest()
else: print ("Not a Test")
